/*
 * =====================================================================================
 *
 *       Filename:  1-5.cpp
 *
 *    Description:  编程珠玑问题1-5
 *
 *        Version:  1.0
 *        Created:  2011-11-9 16:35:30
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (),
 *        Company:
 *
 * =====================================================================================
 */
#include "1-sort.h"

#include <fstream>
#include <sstream>
#include <boost/program_options.hpp>
namespace po = boost::program_options;


void file_gen_file(const std::string &name)
{
    int cnt = MAX_INT / 8 + 1;
    char *A = new char[cnt];

    int tmp = 0;

    for (int k = 1; k <= 2; ++k) {
        //清除标志
        memset(A, 0, cnt * sizeof(char));
        std::fstream in(name.c_str());

        while (in >> tmp) {
            if ((k - 1)*MAX_INT <= tmp && tmp < MAX_INT * k) {
                set_bit(A, tmp - (k - 1)*MAX_INT);
            }
        }

        //输出已经排序的文件
        std::stringstream ss;
        ss << name << ".stxt" << k;
        std::ofstream file(ss.str().c_str());

        for (int i = 0; i < MAX_INT; ++i) {
            if (bit(A, i)) {
                file << i + (k - 1)*MAX_INT << std::endl;
            }
        }

        file.close();
    }

    delete [] A;
}

void _sort_file1(const std::string &name1, const std::string &name2, const std::string &name)
{
    int tmp1 = 0, tmp2 = 0;

    //利用归并排序输出最终文件
    std::ifstream in1(name1.c_str());
    std::ifstream in2(name2.c_str());
    std::ofstream out(name.c_str());

    bool f1 = in1 >> tmp1;
    bool f2 = in2 >> tmp2;

    while (f1 && f2) {
        if (tmp1 < tmp2) {
            out << tmp1 << std::endl;
            f1 = in1 >> tmp1;
        } else {
            out << tmp2 << std::endl;
            f2 = in2 >> tmp2;
        }
    }

    while (f1) {
        out << tmp1 << std::endl;
        f1 = in1 >> tmp1;
    }

    while (f2) {
        out << tmp2 << std::endl;
        f2 = in2 >> tmp2;
    }
}

void sort_file1(const std::string &name)
{
    _sort_file1(std::string(name + ".stxt1").c_str(),
                std::string(name + ".stxt2").c_str(),
                std::string(name + ".1stxt").c_str());
}

int main(int argc, char *argv[])
{
    // Declare the supported options.
    po::options_description desc("Allowed options");
    desc.add_options()
    ("help", "sort no duplcate inter value")
    ("file", po::value<std::string>(), "set need to be sorted file, and the minmum count lines should be 1,250,000")
    ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout << desc << "\n";
        return 1;
    }

    if (vm.count("file")) {
        std::string name = vm["file"].as<std::string>();
        std::cout << "file was set to " << name << ".\n";

        clock_t start = clock();
        file_gen_file(name);
        clock_t finish = clock();
        std::cout << "the running time of file_gen_file is " << (finish - start) / CLOCKS_PER_SEC << std::endl;

        start = clock();
        sort_file1(name);
        finish = clock();
        std::cout << "the running time of sort_file1 is " << (finish - start) / CLOCKS_PER_SEC << std::endl;
    } else {
        std::cout << "file was not set.\n";
    }

    return 0;
}
